[HVM][SVM] Fix 1/2 to interrupt delivery logic.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 20 Oct 2006 09:09:55 +0000 (10:09 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 20 Oct 2006 09:09:55 +0000 (10:09 +0100)
This patch uses the VINTR intercept to signal the hypervisor when a
guest can take an interrupt.  When guest's interrupts are masked by
EFLAGS.IF or the guests are in an interrupt shadow, we create a 'fake'
virtual interrupt to inject while also enabling the VINTR intercept.
When the guest _can_ take interrupts, the hypervisor will #VMEXIT
on VINTR. The VINTR exit handler then clears the VINTR intercept bit
and clears the V_IRQ bit so that svm_intr_assist() can inject a
legitimate interrupt.

Signed-off-by: Travis Betak <travis.betak@amd.com>
Signed-off-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Tom Woller <thomas.woller@amd.com>
xen/arch/x86/hvm/svm/intr.c
xen/arch/x86/hvm/svm/svm.c

index 140df0d636505971d71785bacdcee24d39e097d0..af1b69deb5ecb63ffffd52b61264e7a7e1d63604 100644 (file)
@@ -43,7 +43,7 @@
  * to be suitable for SVM.
  */
 
-static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
+static inline int svm_inject_extint(struct vcpu *v, int trap)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     vintr_t intr;
@@ -87,6 +87,16 @@ asmlinkage void svm_intr_assist(void)
         re_injecting = 1;
     }
 
+    /*
+     * create a 'fake' virtual interrupt on to intercept as soon
+     * as the guest _can_ take interrupts
+     */
+    if (irq_masked(vmcb->rflags) || vmcb->interrupt_shadow) {
+        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+        svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
+        return;
+    }
+
     /* Guest's interrputs masked? */
     rflags = vmcb->rflags;
     if (irq_masked(rflags)) {
@@ -146,7 +156,7 @@ asmlinkage void svm_intr_assist(void)
             }
             /* let's inject this interrupt */
             TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
-            svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
+            svm_inject_extint(v, intr_vector);
             hvm_interrupt_post(v, intr_vector, intr_type);
             break;
         case APIC_DM_SMI:
index 6c78d9986de45a863ef64835542e6e8578b62976..4ce428be5e0bb83733107f4505adc33ad0b18466 100644 (file)
@@ -2811,6 +2811,11 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
         svm_inject_exception(v, TRAP_double_fault, 1, 0);
         break;
 
+    case VMEXIT_VINTR:
+       vmcb->vintr.fields.irq = 0;
+       vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR;
+       break;
+
     case VMEXIT_INTR:
         break;